package cn.t.repository.impl.device;

import cn.t.converter.device.DeviceConverter;
import cn.t.core.repoistory.RepositoryImpl;
import cn.t.model.device.DeviceDO;
import cn.t.persistence.entity.device.DevicePO;
import cn.t.persistence.mapper.device.DeviceMapper;
import cn.t.repository.device.DeviceRepository;
import cn.t.request.InventoryReq;
import cn.t.vo.device.InventoryCargowayVO;
import cn.t.vo.device.InventoryDeviceVO;
import cn.t.vo.device.InventorySkuVO;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 设备表(Device)数据仓库
 *
 * @author t
 * @since 2024-05-24 10:18:08
 */
@Slf4j
@Repository
@AllArgsConstructor
public class DeviceRepositoryImpl extends RepositoryImpl<DeviceMapper, DevicePO, DeviceConverter, DeviceDO> implements DeviceRepository {

    @Override
    public List<DeviceDO> queryById(Collection<Long> deviceIdSet) {
        LambdaQueryChainWrapper<DevicePO> wrapper = lambdaQuery();
        wrapper.in(DevicePO::getId, deviceIdSet).last(" order by id asc");

        List<DevicePO> list = wrapper.list();
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }

        return list.stream().map(converter::po2Model).collect(Collectors.toList());
    }

    @Override
    public List<DeviceDO> findByModel(DeviceDO deviceDO, int start, Integer pageSize, String field, String direction) {

        String lastSql = StringUtils.hasText(field) ?
                " order by " + field + " " + direction + " limit " + start + "," + pageSize : " limit " + start + "," + pageSize;

        List<DevicePO> list = getWrapper(deviceDO).last(lastSql).list();
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }

        return list.stream().map(converter::po2Model).collect(Collectors.toList());
    }

    private LambdaQueryChainWrapper<DevicePO> getWrapper(DeviceDO deviceDO) {
        LambdaQueryChainWrapper<DevicePO> wrapper = lambdaQuery();
        if (!ObjectUtils.isEmpty(deviceDO.getDeviceName())) {
            wrapper.like(DevicePO::getDeviceName, deviceDO.getDeviceName());
        }
        if (!ObjectUtils.isEmpty(deviceDO.getImei())) {
            wrapper.eq(DevicePO::getImei, deviceDO.getImei());
        }
        if (!ObjectUtils.isEmpty(deviceDO.getDeviceAddr())) {
            wrapper.like(DevicePO::getDeviceAddr, deviceDO.getDeviceAddr());
        }
        if (!ObjectUtils.isEmpty(deviceDO.getFirmId())) {
            wrapper.eq(DevicePO::getFirmId, deviceDO.getFirmId());
        }
        if (!ObjectUtils.isEmpty(deviceDO.getDeviceType())) {
            wrapper.eq(DevicePO::getDeviceType, deviceDO.getDeviceType());
        }
        if (!ObjectUtils.isEmpty(deviceDO.getStatus())) {
            wrapper.eq(DevicePO::getStatus, deviceDO.getStatus());
        }
        if (!ObjectUtils.isEmpty(deviceDO.getDeviceTypeList())) {
            wrapper.in(DevicePO::getDeviceType, deviceDO.getDeviceTypeList());
        }
        if (!ObjectUtils.isEmpty(deviceDO.getProvinceId())) {
            wrapper.eq(DevicePO::getProvinceId, deviceDO.getProvinceId());
        }
        if (!ObjectUtils.isEmpty(deviceDO.getCityId())) {
            wrapper.eq(DevicePO::getCityId, deviceDO.getCityId());
        }
        if (!ObjectUtils.isEmpty(deviceDO.getCountyId())) {
            wrapper.eq(DevicePO::getCountyId, deviceDO.getCountyId());
        }
        if (!ObjectUtils.isEmpty(deviceDO.getCtrlBoardNo())) {
            wrapper.eq(DevicePO::getCtrlBoardNo, deviceDO.getCtrlBoardNo());
        }
        if (!ObjectUtils.isEmpty(deviceDO.getCardReaderId())) {
            wrapper.eq(DevicePO::getCardReaderId, deviceDO.getCardReaderId());
        }
        if (!ObjectUtils.isEmpty(deviceDO.getGmtCreatedStart())) {
            wrapper.gt(DevicePO::getGmtCreated, deviceDO.getGmtCreatedStart());
        }
        wrapper.eq(deviceDO.getId() != null, DevicePO::getId, deviceDO.getId());
        wrapper.eq(StringUtils.hasText(deviceDO.getUpgrade()), DevicePO::getUpgrade, deviceDO.getUpgrade());
        wrapper.in(!CollectionUtils.isEmpty(deviceDO.getDeviceIds()), DevicePO::getId, deviceDO.getDeviceIds());
        wrapper.in(!CollectionUtils.isEmpty(deviceDO.getImeiList()), DevicePO::getImei, deviceDO.getImeiList());
        wrapper.eq(deviceDO.getIsMaster() != null, DevicePO::getIsMaster, deviceDO.getIsMaster());
        wrapper.eq(deviceDO.getIsLock() != null, DevicePO::getIsLock, deviceDO.getIsLock());
        return wrapper;
    }

    @Override
    public long count(DeviceDO deviceDO) {
        return getWrapper(deviceDO).count();
    }

    @Override
    public List<DeviceDO> getDeviceList(DeviceDO deviceVo,List<Long> ids) {
        LambdaQueryChainWrapper<DevicePO> wrapper = lambdaQuery();
        wrapper.like(!ObjectUtils.isEmpty(deviceVo.getDeviceName()),DevicePO::getDeviceName, deviceVo.getDeviceName());
        wrapper.in(!CollectionUtils.isEmpty(ids), DevicePO::getId, ids);
        wrapper.eq(!ObjectUtils.isEmpty(deviceVo.getFirmId()), DevicePO::getFirmId, deviceVo.getFirmId());
        List<DevicePO> list = wrapper.list();
        return  converter.pd2DoList(list);
    }

    @Override
    public boolean updateBatch(List<DeviceDO> deviceDOS) {

        if (CollectionUtils.isEmpty(deviceDOS)) {
            return false;
        }

        return this.saveOrUpdateBatch(deviceDOS.stream().map(converter::model2Po).collect(Collectors.toList()));
    }

    @Override
    public void updateVersion(DeviceDO deviceDO) {
        LambdaUpdateChainWrapper<DevicePO> wrapper = lambdaUpdate();
        wrapper.eq(DevicePO::getImei, deviceDO.getImei());
        wrapper.set(DevicePO::getCurrentVersion, deviceDO.getCurrentVersion());
        wrapper.update();
    }

    @Override
    public List<DeviceDO> getDevicesByFirmId(Long firmId) {
        LambdaQueryChainWrapper<DevicePO> wrapper = lambdaQuery();
        wrapper.eq(firmId != null, DevicePO::getFirmId, firmId);
        List<DevicePO> list = wrapper.list();
        return converter.pd2DoList(list);
    }

    @Override
    public List<InventoryDeviceVO> findInventoryDevicePage(Integer pageNo, Integer pageSize, InventoryReq param) {
        return getBaseMapper().findInventoryDevicePage(pageNo, pageSize, param);
    }

    @Override
    public Long getInventoryDeviceCount(InventoryReq param) {
        return getBaseMapper().getInventoryDeviceCount(param);
    }

    @Override
    public List<InventorySkuVO> findInventorySkuPage(Integer pageNo, Integer pageSize, InventoryReq param) {
        return getBaseMapper().findInventorySkuPage(pageNo, pageSize, param);
    }

    @Override
    public Long getInventorySkuCount(InventoryReq param) {
        return getBaseMapper().getInventorySkuCount(param);
    }

    @Override
    public List<InventoryCargowayVO> findCargowayPage(Integer pageNo, Integer pageSize, InventoryReq param) {
        return getBaseMapper().findCargowayPage(pageNo, pageSize, param);
    }

    @Override
    public Long getInventoryCargowayCount(InventoryReq param) {
        return getBaseMapper().getInventoryCargowayCount(param);
    }
}
